package cn.feng.enhance.a2_reflect;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;

import org.junit.Test;

public class ReflectTest {

	@SuppressWarnings("rawtypes")
	@Test
	public void testReflect1() throws Exception {
		String str = "abc";
		Class clazz = str.getClass();
		Class clazz2 = String.class;
		Class clazz3 = Class.forName("java.lang.String");
		System.out.println(clazz == clazz3);
		System.out.println(clazz == clazz2);
		// 是基本类型吗isPrimitive();
		System.out.println("是基本类型吗:" + clazz.isPrimitive());
		System.out.println("是基本类型吗:" + int.class.isPrimitive());
		System.out.println(int.class == Integer.class);
		System.out.println(int.class == Integer.TYPE);
		System.out.println("是基本类型吗:" + int[].class.isPrimitive());
		System.out.println("是数组吗:" + int[].class.isArray());

		Constructor constructor = String.class.getConstructor(StringBuffer.class);
		String string = (String) constructor.newInstance(new StringBuffer("abc"));
		System.out.println("字符串" + string.charAt(2));
		System.out.println();
		System.out.println();
	}

	@Test
	public void testReflectFiled() throws Exception {

		ReflectPoint reflectPoint = new ReflectPoint(2, 4);
		System.out.println(reflectPoint);

		Field fieldY = reflectPoint.getClass().getField("y");
		// fieldY的值是多少？是5,错！fieldY不是对象身上的变量，而是类上，要用它去取某个对象上对应的值
		System.out.println(fieldY.get(reflectPoint));
		// 无法获取私有的字段值
		// Field fieldX = reflectPoint.getClass().getField("x");
		// System.out.println(fieldX.get(reflectPoint));

		// 获取私有的字段值
		Field fieldX2 = reflectPoint.getClass().getDeclaredField("x");
		// 暴力反射
		fieldX2.setAccessible(true);
		System.out.println(fieldX2.get(reflectPoint));
		// Map<String, Integer>map={"a":2};
	}

	@Test
	public void testReflectFiled2() throws Exception {

		ReflectPoint reflectPoint = new ReflectPoint(3, 7);
		System.out.println(reflectPoint);
		changeStringValue(reflectPoint);
		System.out.println(reflectPoint);
	}

	private void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
		Field[] fields = obj.getClass().getFields();
		for (Field field : fields) {
			// 同一个字节码文件 ,字节码文件用==
			if (field.getType() == String.class) {
				String oldValue = (String) field.get(obj);
				String newValue = oldValue.replace('a', 'c');
				field.set(obj, newValue);
			}
		}
	}

	/**
	 * 方法反射
	 */
	@Test
	public void testReflectMethodInvoke() throws NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		ReflectPoint reflectPoint = new ReflectPoint(8, 45);
		String string = "abc";
		Method method = String.class.getMethod("charAt", int.class);
		// System.out.println(method.invoke(null, 1));第一个参数是null表示这是一个静态方法,

		// string表示用对象,2表示方法的参数
		System.out.println(method.invoke(string, 2));
		System.out.println(method.invoke(string, new Object[] { 2, }));
	}

	@Test
	public void testReflectMain() throws NoSuchMethodException, SecurityException, ClassNotFoundException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		String args = "cn.feng.enhance.a2_reflect.TestArguments";
		Method method = Class.forName(args).getMethod("main", String[].class);
		method.invoke(null, new Object[] { new String[] { "111", "333", "222", } });
		method.invoke(null, (Object) new String[] { "111", "333", "222", });

	}

	/**
	 * 数组反射
	 */
	@Test
	public void testReflectArray() {
		int[] arr1 = new int[4];
		int[] arr2 = new int[] { 1, 3, 2, 5, };
		int[] arr3 = { 1, 3, 4, };
		System.out.println(arr1.getClass() == arr3.getClass());
		System.out.println(arr1.getClass() == arr2.getClass());
		System.out.println("name:" + arr1.getClass().getName());
		System.out.println("name:" + arr2.getClass().getName());
		System.out.println("name:" + arr3.getClass().getName());
		System.out.println("supername:" + arr3.getClass().getSuperclass().getName());
		System.out.println("supername:" + arr3.getClass().getSuperclass().getName());
		System.out.println("supername:" + arr3.getClass().getSuperclass().getName());
		Object objects = arr1;
		printArray(objects);
		printArray("bcd");
	}

	private void printArray(Object objects) {
		Class<? extends Object> class1 = objects.getClass();
		if (class1.isArray()) {
			for (int i = 0; i < Array.getLength(objects); i++) {
				System.out.println(Array.get(objects, i));
			}
		} else {
			System.out.println(objects);
		}
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testCollections() throws IOException, InstantiationException, IllegalAccessException,
			ClassNotFoundException {
		// TODO Auto-generated method stub
		/*
		 * getRealPath();//金山词霸/内部 一定要记住用完整的路径，但完整的路径不是硬编码，而是运算出来的。
		 */
		// InputStream ips = new FileInputStream("config.properties");

		// InputStream ips =
		// ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
		// InputStream ips =
		// ReflectTest2.class.getResourceAsStream("resources/config.properties");

		// 加载源文件
		InputStream resourceAsStream = ReflectTest.class
				.getResourceAsStream("/cn/feng/enhance/a2_reflect/resource/load.properties");
		Properties properties = new Properties();
		// 加载
		properties.load(resourceAsStream);
		resourceAsStream.close();
		// 获取属性
		String object = (String) properties.getProperty("className");

		// 反射
		Collection collection = (Collection) Class.forName(object).newInstance();

		collection.add(new ReflectPoint(2, 3));
		collection.add(new ReflectPoint(2, 3));
		collection.add(new ReflectPoint(2, 3));
		collection.add(new ReflectPoint(2, 3));
		collection.add(new ReflectPoint(2, 3));

		System.out.println(collection.size());

	}
}

class TestArguments {
	public static void main(String args[]) {
		for (int i = 0; i < args.length; i++) {
			System.out.println(args.toString());

		}
	}
}

class ReflectPoint {
	private int x;
	public int y;
	public String str1 = "ball";
	public String str2 = "keyboard";

	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public String getStr1() {
		return str1;
	}

	public void setStr1(String str1) {
		this.str1 = str1;
	}

	public String getStr2() {
		return str2;
	}

	public void setStr2(String str2) {
		this.str2 = str2;
	}

	@Override
	public String toString() {
		return "ReflectPoint [x=" + x + ", y=" + y + ", str1=" + str1 + ", str2=" + str2 + "]";
	}

}